﻿using iTool.SQL.Analysis.ColumnRef;
using iTool.SQL.Analysis.Common;
using iTool.SQL.Analysis.Context;
using iTool.SQL.Analysis.FromClause;
using iTool.SQL.Analysis.GroupByClause;
using iTool.SQL.Analysis.HavingClause;
using iTool.SQL.Analysis.OrderByClause;
using iTool.SQL.Analysis.SelectClause;
using iTool.SQL.Analysis.SetClause;
using iTool.SQL.Analysis.Statement;
using iTool.SQL.Analysis.SubQuery;
using iTool.SQL.Analysis.TableConstructorInsert;
using iTool.SQL.Analysis.TableRef;
using iTool.SQL.Analysis.WhereClause;
using Microsoft.SqlServer.Management.SqlParser.Parser;
using Microsoft.SqlServer.Management.SqlParser.SqlCodeDom;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace iTool.SQL.Analysis
{
    public class SqlAnalysisFactory
    {

        public static SqlAnalysisBase CreateStatementAnalysisInstance(string sql)
        {
            Console.WriteLine(sql);
            var result = SqlUtils.Parse(sql);

            if (result.Errors.Any())
            {
                foreach (var item in result.Errors)
                {
                    Console.WriteLine(item.Message);
                }
            }

            // logger
            SqlUtils.IterateSqlNode(result.Script);

            SqlAnalysisBase statement = new SqlSelectStatementAnalysis();
            if (statement.Validation(result.Script))
                return statement;

            statement = new SqlDeleteStatementAnalysis();
            if (statement.Validation(result.Script))
                return statement;

            statement = new SqlInsertStatementAnalysis();
            if (statement.Validation(result.Script))
                return statement;

            statement = new SqlUpdateStatementAnalysis();
            if (statement.Validation(result.Script))
                return statement;

            throw new Exception("no find statement");

        }

        public static SqlAnalysisBase GetNextSqlAnalysis<TIn>(SqlAnalysisContext context) 
            where TIn : SqlCodeObject
        {
            return GetNextSqlAnalysis(typeof(TIn), context);
        }

        public static SqlAnalysisBase GetNextSqlAnalysis(Type type, SqlAnalysisContext context)
        {

            switch (type)
            {
                case var t when t == typeof(SqlTableRefExpression):
                    return new SqlTableRefExpressionAnalysis(context);

                case var t when t == typeof(SqlBetweenBooleanExpression):
                    return new SqlBetweenBooleanExpressionAnalysis(context);

                case var t when t == typeof(SqlBinaryBooleanExpression):
                    return new SqlBinaryBooleanExpressionAnalysis(context);

                case var t when t == typeof(SqlComparisonBooleanExpression):
                    return new SqlComparisonBooleanExpressionAnalysis(context);

                case var t when t == typeof(SqlInBooleanExpression):
                    return new SqlInBooleanExpressionAnalysis(context);

                case var t when t == typeof(SqlLikeBooleanExpression):
                    return new SqlLikeBooleanExpressionAnalysis(context);

                case var t when t == typeof(SqlWhereClause):
                    return new SqlWhereClauseAnalysis(context);

                case var t when t == typeof(SqlInBooleanExpressionCollectionValue):
                    return new SqlInBooleanExpressionCollectionValueAnalysis(context);

                case var t when t == typeof(SqlColumnRefExpression):
                    return new SqlColumnRefExpressionAnalysis(context);

                case var t when t == typeof(SqlSearchedCaseExpression):
                    return new SqlSearchedCaseExpressionAnalysis(context);

                case var t when t == typeof(SqlSearchedWhenClause):
                    return new SqlSearchedWhenClauseAnalysis(context);

                case var t when t == typeof(SqlScalarSubQueryExpression):
                    return new SqlScalarSubQueryExpressionAnalysis(context);

                case var t when t == typeof(SqlQuerySpecification):
                    return new SqlQuerySpecificationAnalysis(context);

                case var t when t == typeof(SqlInBooleanExpressionQueryValue):
                    return new SqlInBooleanExpressionQueryValueAnalysis(context);

                case var t when t == typeof(SqlExistsBooleanExpression):
                    return new SqlExistsBooleanExpressionAnalysis(context);
                    
                case var t when t == typeof(SqlIsNullBooleanExpression):
                    return new SqlIsNullBooleanExpressionAnalysis(context);

                case var t when t == typeof(SqlSetClause):
                    return new SqlSetClauseAnalysis(context);

                case var t when t == typeof(SqlColumnAssignment):
                    return new SqlColumnAssignmentAnalysis(context);

                case var t when t == typeof(SqlAggregateFunctionCallExpression):
                    return new SqlAggregateFunctionCallExpressionAnalysis(context);

                case var t when t == typeof(SqlRowConstructorExpression):
                    return new SqlRowConstructorExpressionAnalysis(context);

                case var t when t == typeof(SqlTableConstructorExpression):
                    return new SqlTableConstructorExpressionAnalysis(context);

                case var t when t == typeof(SqlTableConstructorInsertSource):
                    return new SqlTableConstructorInsertSourceAnalysis(context);

                case var t when t == typeof(SqlBinaryQueryExpression):
                    return new SqlBinaryQueryExpressionAnalysis(context);
                    
                case var t when t == typeof(SqlFromClause):
                    return new SqlFromClauseAnalysis(context);

                case var t when t == typeof(SqlSelectClause):
                    return new SqlSelectClauseAnalysis(context);

                case var t when t == typeof(SqlTopSpecification):
                    return new SqlTopSpecificationAnalysis(context);

                case var t when t == typeof(SqlSelectStarExpression):
                    return new SqlSelectStarExpressionAnalysis(context);

                case var t when t == typeof(SqlSelectScalarExpression):
                    return new SqlSelectScalarExpressionAnslysis(context);

                case var t when t == typeof(SqlBinaryScalarExpression):
                    return new SqlBinaryScalarExpressionAnalysis(context);

                case var t when t == typeof(SqlQualifiedJoinTableExpression):
                    return new SqlQualifiedJoinTableExpressionAnalysis(context);

                case var t when t == typeof(SqlOrderByItem):
                    return new SqlOrderByItemAnalysis(context);

                case var t when t == typeof(SqlOrderByClause):
                    return new SqlOrderByClauseAnalysis(context);

                case var t when t == typeof(SqlGroupByClause):
                    return new SqlGroupByClauseAnalysis(context);

                case var t when t == typeof(SqlSimpleGroupByItem):
                    return new SqlSimpleGroupByItemAnalysis(context);

                case var t when t == typeof(SqlHavingClause):
                    return new SqlHavingClauseAnalysis(context);

                case var t when t == typeof(SqlStatementError):
                    return new SqlStatementErrorOfLimitAnalysis(context);

                case var t when t == typeof(SqlDerivedTableExpression):
                    return new SqlDerivedTableExpressionAnalysis(context);

                case var t when t == typeof(SqlScalarVariableRefExpression):
                    return new SqlScalarVariableRefExpressionAnalysis(context);

                case var t when t.FullName.Contains("TwoPartObjectIdentifier"):
                    return new TwoPartObjectIdentifierAnalysis(context);

                case var t when t.FullName.Contains("OnePartObjectIdentifier"):
                    return new OnePartObjectIdentifierAnalysis(context);

                case var t when t.FullName.Contains("IntegerLiteralExpression"):
                    return new IntegerLiteralAnalysis(context);

                case var t when t.FullName.Contains("NumericLiteralExpression"):
                    return new NumericLiteralAnalysis(context);

                case var t when t.FullName.Contains("StringLiteralExpression"):
                    return new StringLiteralAnalysis(context);

                case var t when t.FullName.Contains("SqlBuiltinScalarFunctionCallExpression"):
                    return new SqlBuiltinScalarFunctionCallAnalysis(context);

                case var t when t.FullName.Contains("SqlColumnOrPropertyRefExpression"):
                    return new SqlColumnOrPropertyRefExpressionAnalysis(context);

                default:
                    Console.WriteLine(type);
                    return new CommonAnalysis(context);
            }

        }
    }
}
